package com.wuad.platformwuad.module.study.activiti7Demo.threeTest;

import org.activiti.engine.*;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

public class ThreeTest {

    public static final String PROCESS_DEFINITION_KEY = "myProcess";

    /**
     * PENDING表示任务正在协办
     * RESOLVED表示协办结束
     *
     */

    /**
     * 第一步：
     * （1）创建activit7所需的表结构，会创建25张表，
     * （2）act_ge_property表会入库activitiv7的一些属性信息，四条数据
     * （3）如果把act_ge_property表数据清空，在运行就会报错
     */
    @Test
    public void createActivitiTable() {
        ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
        processEngineConfiguration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        processEngineConfiguration.setJdbcUrl("jdbc:mysql://localhost:3306/platform_wad?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true");
        processEngineConfiguration.setJdbcUsername("root");
        processEngineConfiguration.setJdbcPassword("root");

        //DB_SCHEMA_UPDATE_TRUE 如果表不存在 自动创建表
        processEngineConfiguration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        //工作流核心对象 processEngine
        ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
        System.out.println("processEngine:"+processEngine);
    }

    /**
     * 第二步：流程部署
     */
    /**
     * （1）部署流程定义：将下面代码中指定的bpmn文件和png文件保存到Activiti数据库中
     *
     * （2）act_re_deployment （一条） 部署信息，不同的流程对应不同的数据
     * （3）act_re_procdef 流程定义的一些信息
     * （4）act_ge_bytearray表入库数据（两条数据）：流程定义bpmn文件和png文件
     */
    @Test
    public void devlopModle() {
        // 第三种
        // 创建ProcessEngineConfiguration对象
        ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
        ProcessEngine processEngine = configuration.buildProcessEngine();
        //获取RepositoryService对象
        RepositoryService repositoryService = processEngine.getRepositoryService();
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("process/MyProcess.zip");
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);
        //进行部署
        Deployment deployment = repositoryService
                .createDeployment()
                .addZipInputStream(zipInputStream)
                .name("助农点申请流程")
                // 部署
                .deploy();
        //输出部署的一些信息
        System.out.println("流程部署id = " + deployment.getId());
        System.out.println("流程部署名称 = " + deployment.getName());
        System.out.println("33333" + deployment.getDeploymentTime());
        System.out.println("44444" + deployment.getCategory());
        System.out.println("55555" + deployment.getTenantId());
        System.out.println("流程部署key = " + deployment.getKey());
        System.out.println("66666" + deployment.getProjectReleaseVersion());
        System.out.println("77777" + deployment.getVersion());
    }

    /**
     * 第三步：根据已部署的流程，创建流程实例
     *
     * act_hi_actinst 活动实例
     * act_hi_identitylink 参与者信息
     * act_hi_procinst 流程实例
     * act_hi_taskinst 任务实例
     * act_ru_execution 执行表
     * act_ru_identitylink 参与者信息
     * act_ru_task   任务表
     */
    @Test
    public void beginTest() {
        String businessKey = "业务关联用id";
        //创建ProcessEngineConfiguration对象
        ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
        ProcessEngine processEngine = configuration.buildProcessEngine();
        //获取RuntimeService对象
        RuntimeService runtimeService = processEngine.getRuntimeService();
        // 设置流程执行人
        Map<String, Object> variables = new HashMap<>();
        variables.put("user", "第一个审批人");
        //根据流程定义的key启动流程实例（这个id是MyProcess.xml里面的id）
//        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(PROCESS_DEFINITION_KEY,variables);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(PROCESS_DEFINITION_KEY,businessKey,variables);
        //获取流程实例的相关信息
        System.out.println("流程定义的id = " + processInstance.getProcessDefinitionId());
        System.out.println("这是个啥：" + processInstance.getProcessDefinitionKey());
        System.out.println("流程部署的id = " + processInstance.getDeploymentId());
        System.out.println("流程实例的id = " + processInstance.getId());
        System.out.println("当前活动的id = " + processInstance.getActivityId());
        System.out.println("业务关联用id = " + processInstance.getBusinessKey());
    }

    /**
     * （4）查询流程
     * 流程启动后，各个任务的负责人就可以查询自己当前需要处理的任务，查询出来的任务都是该用户的待办任务
     */
    @Test
    public void selectTest() {
        //任务负责人
        String assignee = "第一个审批人";
        //创建ProcessEngineConfiguration对象
        ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
        ProcessEngine processEngine = configuration.buildProcessEngine();
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();
        //查询任务列表，根据流程定义的key和任务负责人
        List<Task> taskList = taskService
                .createTaskQuery()
                .processDefinitionKey(PROCESS_DEFINITION_KEY)
//                .processInstanceId("17501")
                .taskAssignee(assignee)
                .list();
        System.out.println("任务列表：" + taskList);
        //遍历任务列表
        for (Task task : taskList) {
            System.out.println("流程定义id = " + task.getProcessDefinitionId());
            System.out.println("流程实例id = " + task.getProcessInstanceId());
            System.out.println("任务负责人 = " + task.getAssignee());
            System.out.println("任务id = " + task.getId());
            System.out.println("任务名称 = " + task.getName());
        }
    }

    /**
     * （5）处理流程
     * 任务负责人查询待办任务，选择任务进行处理，完成任务, 并可指定下个节点审批人。
     *
     * act_hi_actinst 活动实例
     * act_hi_identitylink 参与者信息
     * act_hi_taskinst 任务实例
     * act_ru_execution 执行表
     * act_ru_identitylink 参与者信息
     * act_ru_task 任务表
     */
    @Test
    public void disposeTest() {
        //任务负责人
        String assignee = "第二个审批人";
        // 业务关联id
        String businessKey = "业务关联用id";
        //创建ProcessEngineConfiguration对象
        ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
        ProcessEngine processEngine = configuration.buildProcessEngine();
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();
        //查询任务列表，根据流程定义的key和任务负责人
//        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey("myProcess").taskAssignee(assignee).list();
        List<Task> taskList = taskService.createTaskQuery().processInstanceBusinessKey(businessKey).list();
        System.out.println("这是个啥：" + taskList);
        // 设置流程执行人
        Map<String, Object> variables = new HashMap<>();
        variables.put("user", "第三个审批人");
        //遍历任务列表
        for (Task task : taskList) {
            String id = task.getId();

            // 添加审批意见
            //需要添加此句否则审批意见表中ACT_HI_COMMENT，审批人的userId是空的
            Authentication.setAuthenticatedUserId(assignee);
            taskService.addComment(id, task.getProcessInstanceId(),"这是填的审批意见");
            //完成任务
//            taskService.complete(id);
            taskService.complete(id, variables);
        }
    }



    /**
     * 修改流程审批人：流程转让
     *
     * 修改assignee字段属性
     */
    @Test
    public void updateAssignee() {
        String taskId = "27502";
        String userId = "第三个审批人";
        //创建ProcessEngineConfiguration对象
        ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
        ProcessEngine processEngine = configuration.buildProcessEngine();
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();
        //
        taskService.delegateTask(taskId, userId);
    }

    /**
     * 流程退回: 回退给指定人
     *
     * 修改assignee字段属性
     */
    @Test
    public void returnedTest() {
        String taskId = "27502";
        String userId = "我是第二个审批人";
        //创建ProcessEngineConfiguration对象
        ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
        ProcessEngine processEngine = configuration.buildProcessEngine();
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();

        Map<String, Object> variables = new HashMap<>();
        variables.put("user", userId);

//        Authentication.setAuthenticatedUserId("我是第三个审批人");
//        taskService.addComment(id, task.getProcessInstanceId(),"这是填的审批意见");
        taskService.resolveTask(taskId, variables);
    }

    /**
     * 查询审批意见
     */
    public void selectYIJIAN() {
//        List<Comment> comments=taskService.getTaskComments(taskId);
    }

    /**
     * 任务认领： 给taskId签名，设置Assignee;
     *
     * 官方解释：声明任务的责任:指定的用户成为该任务的受让人
     */
    @Test
    public void updateUserTest() {
        String taskId = "20006";
        String userId = "第一个审批人";
        //创建ProcessEngineConfiguration对象
        ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti-cfg.xml");
        ProcessEngine processEngine = configuration.buildProcessEngine();
        //获取TaskService对象
        TaskService taskService = processEngine.getTaskService();
        //
        taskService.claim(taskId, userId);
        // 如果上面这个方法执行报错，先执行下面这个再执行上面这个就不报错了
//        taskService.unclaim(taskId);
    }
}
